﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Text;

namespace NetFrame.Auto
{
    public static class LengthEncoding
    {
        /// <summary>
        /// 粘包长度编码，即将在数据的前面加上数据的长度，在获取数据时根据长度判断数据是否完整
        /// </summary>
        /// <param name="buff"></param>
        /// <returns></returns>
        public static byte[] Encode(byte[] buff)
        {
            using (MemoryStream ms = new MemoryStream())
            {
                using (BinaryWriter sw = new BinaryWriter(ms))
                {
                    sw.Write(buff.Length);
                    //写入消息体
                    sw.Write(buff);
                    byte[] result = new byte[ms.Length];
                    Buffer.BlockCopy(ms.GetBuffer(), 0, result, 0, (int)ms.Length);

                    return result;
                }
            }
        }

        /// <summary>
        /// 粘包长度解码，即把数据包的长度去掉还原真实的数据
        /// </summary>
        /// <param name="cache"></param>
        /// <returns></returns>
        public static byte[] Decode(ref List<byte> cache)
        {
            // 4其实是Encode方法中sw.Write(buff.Length)=》int的长度
            // 因为如果只剩下长度，那肯定是没有数据的
            if (cache.Count < 4)
            {
                return null;
            }

            using (MemoryStream ms = new MemoryStream(cache.ToArray()))
            {
                using (BinaryReader br = new BinaryReader(ms))
                {
                    // 从缓存中读取int型消息体长度
                    int length = br.ReadInt32();

                    // 如果缓存中数消息体长度 大于据长度 说明消息没有读取完 等待下次消息到达后再次处理
                    if (length > ms.Length - ms.Position)
                    {
                        return null;
                    }
                    // 读取正确长度的数据
                    byte[] result = br.ReadBytes(length);
                    // 清空缓存
                    cache.Clear();
                    // 将读取后的剩余数据写入缓存
                    cache.AddRange(br.ReadBytes((int)(ms.Length - ms.Position)));
                    return result;

                }
            }
        }
    }
}
